from base.client import BaseClient
from utils import ConnectionConfig, BatchProcessor
from utils.exceptions import AuthError
from .spi import MarketSpi
import time
import json
import logging
import hashlib

logger = logging.getLogger('market.api')

class MarketClient(BaseClient):
    """行情专用客户端"""
    def __init__(self, config: ConnectionConfig, spi: MarketSpi):
        super().__init__(config, spi)
        self._init_market()
        self.__authenticated = False  # 行情认证状态
        
        # 确保双向引用
        if spi:
            spi.api = self
            self.spi = spi

    def _init_market(self):
        """行情特有初始化"""
        self._processor = BatchProcessor(
            max_size=50,  # 批量处理50条消息
            timeout=0.1
        )
        self._subscriptions = set()

    def _get_ws_url(self) -> str:
        return f"ws://{self.config.host}:{self.config.market_port}"

    def subscribe(self, market,securityId, append=0):
        """发送订阅请求"""
        sub_msg = {
            "msgType": 3002,
            "reqId": 0,
            "data": 
            {
                "market": market,
                "secType": 0,
                "securityId": securityId,
                "isSubscribe": append
            }
        }
        self.ws.send(json.dumps(sub_msg))

    def _handle_message(self, data):
        """批量处理行情数据"""
        try:
            # 解析JSON数据
            if isinstance(data, str):
                message = json.loads(data)
            else:
                message = data
            
            # 处理特定消息类型
            msg_type = message.get("msgType")
            
            # 处理认证响应
            if msg_type == 3001:  # 认证响应
                self._handle_auth_response(message)
            # 将消息添加到处理队列
            self._processor.add(data)
            
            # 调用SPI回调
            if self.spi:
                self.spi.on_message(data)
        except json.JSONDecodeError:
            logger.warning(f"收到非JSON格式消息: {data[:100]}...")
        except Exception as e:
            logger.error(f"处理消息时发生错误: {e}", exc_info=True)

    def _handle_auth_response(self, message: dict):
        """处理认证响应"""
        error_id = message.get("errorId", -1)
        if error_id == 0:
            self.update_auth_status(True)
        else:
            error_msg = message.get("retMsg", "未知错误")
            logger.error(f"行情认证失败: {error_msg}")
            self.update_auth_status(False)
            # 通知SPI认证失败
            if self.spi:
                self.spi.on_login(False, error_msg=error_msg)

    def connect(self):
        """重写连接流程，加入认证环节"""
        super().connect()
        self.__authenticate()

    def _send(self, data: dict):
        """发送数据"""
        if not self.ws.sock or not self.ws.sock.connected:
            raise ConnectionError("交易连接未就绪")
        
        try:
            self.ws.send(json.dumps(data))
        except Exception as e:
            logger.error(f"订单发送失败: {str(e)}")
            self.reconnect()
            
    def __authenticate(self):
        """行情登录认证（使用独立账户体系）"""
        login_req = {
            "msgType": 3000,
            "reqId": 0,
            "data": {
                "username": self.config.market_username,
                "password": self.config.market_password,
                "envType": 0,
                "version": "1.0.0",
                "veryCode": self.config.auth_code,
                "mac":""
            }
        }
        
        self._send(login_req)
        if not self.__wait_auth():
            raise AuthError("行情认证超时")

    def __wait_auth(self, timeout: int = 15) -> bool:
        """等待认证响应（增加详细跟踪）"""
        logger.debug(f"开始等待行情认证，超时时间: {timeout}s")
        start = time.time()
        while time.time() - start < timeout:
            if self.__authenticated:
                logger.debug("检测到行情认证状态更新")
                return True
            logger.debug(f"当前行情认证状态: {self.__authenticated}，等待中...")
            time.sleep(0.5)
        logger.warning(f"行情认证超时，最后状态: {self.__authenticated}")
        return False

    def update_auth_status(self, status: bool):
        """更新认证状态（增加日志）"""
        logger.debug(f"正在更新行情认证状态: {status}")
        self.__authenticated = status
        if status:
            logger.info("行情认证状态已更新为已认证")
            ready_req = {
                "msgType": 1000,  # 登录消息类型
                "reqId": 0
            }
            self._send(ready_req)

    def _encrypt_password(self) -> str:
        """密码加密（匹配XWebSnap.c的加密方式）"""
        raw = f"{self.config.market_password}{self.config.auth_code}"
        return hashlib.sha256(raw.encode()).hexdigest() 